package com.duoec.doc.service.impl;

import com.duoec.doc.dto.enums.GenderEnum;
import com.duoec.doc.dto.request.UserSaveRequest;
import com.duoec.doc.dto.response.*;
import com.duoec.doc.exceptions.DuoDemoException;
import com.duoec.doc.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ClassUtils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class UserServiceImpl implements UserService {
    private static final Random RANDOM = new SecureRandom();

    @Override
    public UserDetailDto getDetail(long id) {
        return mockUser(id, UserDetailDto.class);
    }

    @Override
    public Boolean delete(long id) {
        checkUserId(id);
        return true;
    }

    @Override
    public UserDto save(UserSaveRequest userDto) {
        return mockUser(null, UserDto.class);
    }

    private <T extends UserDto> T mockUser(Long id, Class<T> clazz) {
        return mockUser(id, clazz, true);
    }

    private <T extends UserDto> T mockUser(Long id, Class<T> clazz, boolean mockFriends) {
        T dto = BeanUtils.instantiateClass(clazz);
        if (id != null) {
            checkUserId(id);
        } else {
            id = (long) RANDOM.nextInt(1000000);
        }
        dto.setId(id);
        dto.setName("张三");
        Role role = new Role();
        role.setId(Math.abs(RANDOM.nextInt(100)) + 100);
        role.setName("普通用户");
        dto.setRole(role);
        List<Article<Vr>> vars = new ArrayList<>();
        int count = RANDOM.nextInt(10);
        for (int i = 0; i < count; i++) {
            vars.add(mockArticle(i));
        }
        dto.setVrs(vars);
        dto.setScore(Math.abs(RANDOM.nextDouble()) + 1000);
        dto.setMoney(BigDecimal.valueOf(Math.abs(RANDOM.nextInt(10000)) + 1000));
        dto.setWeight(Math.abs(RANDOM.nextFloat()) + 1000);
        dto.setFamilyNameFirstLetter('D');
        dto.setGender(GenderEnum.FEMALE);
        dto.setCreateTime(LocalDateTime.now());
        dto.setBirthday(LocalDate.now());
        dto.setUpdateTime(System.currentTimeMillis());
        dto.setRegistryDate(new Date());
        dto.setFamilyGenders(List.of(GenderEnum.FEMALE, GenderEnum.MAN));
        dto.setExtraData(mockExtraData());
        dto.setExtraData2(mockExtraData2());

        List<UserDto> friends = new ArrayList<>();
        count = mockFriends ? RANDOM.nextInt(5) : 0;
        for (int i = 0; i < count; i++) {
            friends.add(mockUser(null, UserDto.class, false));
        }
        dto.setFriends(friends);
        if (!friends.isEmpty()) {
            dto.setBestFriend(friends.get(0));
        }
        return dto;
    }

    private static Map<String, BaseKeyValue> mockExtraData2() {
        Map<String, BaseKeyValue> data = new HashMap<>();
        data.put("name1", new BaseKeyValue("key", "value"));
        data.put("name2", new BaseKeyValue("key2", "value2"));
        return data;
    }

    private static Map<String, Serializable> mockExtraData() {
        Map<String, Serializable> data = new HashMap<>();
        data.put("k1", "v1");
        data.put("k2", 1345);
        return data;
    }

    private static Article<Vr> mockArticle(int index) {
        Article<Vr> article = new Article<>();
        article.setId(String.valueOf(index + 10000));
        article.setTitle("文章标题--mock");
        Vr vr = new Vr();
        vr.setVrUrl("https://www.duoec.com");
        article.setContent(vr);
        return article;
    }

    private static void checkUserId(long id) {
        if (id <= 0) {
            throw new DuoDemoException("用户ID不能小于0");
        }
    }
}
